
package com.idea.rdftree.editor;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.io.File;
import java.io.FileReader;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;

import com.hp.hpl.jena.mem.ModelMem;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.idea.common.rdf.RdfUtils;
import com.idea.common.swing.FileToolUI;
import com.idea.common.swing.FileTools;
import com.idea.common.swing.GeneralApplication;
import com.idea.common.swing.LogPane;
import com.idea.common.swing.WindowKit;
import com.idea.io.FileChooserWrapper;
import com.idea.rdftree.RdfTreeNode;
import com.idea.rdftree.RdfTreePanel;

public class RdfEditor implements TreeSelectionListener, GeneralApplication,
		FileTools {

	private JFrame frame;
	private JPanel panel;
	private NodePanel nodePanel;
	private RdfTreePanel rdfTreePanel;
	private JFileChooser fileChooser;
	// public static LogPane log;
	private FileOpener fileOpener = null;
	private JTabbedPane tabs;
	private TurtleSourcePane turtle;
	private AbbrevSourcePane abbrev;
	private Model model;

	public static final Dimension FRAME_SIZE = new Dimension(600, 600);
	public static final Dimension TREE_PANEL_SIZE = new Dimension(600, 300);
	// public static final Dimension NODE_PANEL_SIZE = new Dimension(100, 200);
	public static final Dimension SOURCE_PANEL_SIZE = new Dimension(600, 300);
	// public static final Dimension LOG_PANEL_SIZE = new Dimension(400, 75);

	public static final Color READ_ONLY_COLOR = (Color) UIManager.getDefaults()
			.get("Button.background");

	public static final Color READ_WRITE_COLOR = (Color) UIManager
			.getDefaults().get("TextField.background");

	public RdfEditor() {
	    model = ModelFactory.createDefaultModel();
		WindowKit.setNativeLookAndFeel();

		panel = new JPanel(new BorderLayout());
		panel.setPreferredSize(FRAME_SIZE);
		// FileToolUI fileUI = new FileToolUI(this);
		// panel.add(fileUI.getToolBar(), BorderLayout.NORTH);

		tabs = new JTabbedPane(JTabbedPane.BOTTOM);

		rdfTreePanel = new RdfTreePanel(true);

		// treePanel.setPreferredSize(TREE_PANEL_SIZE);
		rdfTreePanel.init();
		rdfTreePanel.addTreeSelectionListener(this);
		rdfTreePanel.setCursor(new Cursor(Cursor.HAND_CURSOR));

		tabs.addTab("Tree", rdfTreePanel);

		turtle = new TurtleSourcePane();
		turtle.setModel(model);
		tabs.addChangeListener(turtle);
		// turtle.setPreferredSize(SOURCE_PANEL_SIZE);
		tabs.addTab(turtle.getLabel(), turtle);

		abbrev = new AbbrevSourcePane();
		abbrev.setModel(model);
		tabs.addChangeListener(abbrev);
		// abbrev.setPreferredSize(SOURCE_PANEL_SIZE);
		tabs.addTab(abbrev.getLabel(), abbrev);

		panel.add(tabs, BorderLayout.CENTER);

		JPanel southPanel = new JPanel(new BorderLayout());

		nodePanel = new NodePanel();
		southPanel.add(nodePanel, BorderLayout.NORTH);

		// Control panel
		JPanel controlPanel = new JPanel();
		controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.Y_AXIS));

		FileToolUI fileUI = new FileToolUI(this);

		// fileUI.getToolBar().add(sourcePanel.getRefreshButton());

		controlPanel.add(fileUI.getToolBar());

		panel.add(controlPanel, BorderLayout.NORTH);

		initLogPane();

		frame = new JFrame("RDF Editor");
		JMenuBar menuBar = new JMenuBar();
		menuBar.add(fileUI.getFileMenu());

		frame.setJMenuBar(menuBar);
		frame.setContentPane(panel);
		frame.pack();
	    // frame.show();
		frame.setVisible(true);
		fileChooser = new JFileChooser();
	}

	public static void main(String[] args) {
		WindowKit.setPlastic3DLookAndFeel();
		new RdfEditor();
	}
	
	public Model getModel(){ // TODO try to refactor out
		return model;
	}
	
	private void initLogPane() {
		LogPane log = LogPane.getLogPane();

		JScrollPane logScroll = new JScrollPane(log);
		//logScroll.setPreferredSize(LOG_PANEL_SIZE);
		logScroll.setBorder(BorderFactory.createLoweredBevelBorder());

		// panel.add(logScroll, BorderLayout.SOUTH);

		log.println("Ok.");
		tabs.addTab("Log", log);
	}

	public void newFile() {
	}

	public void openFile() {
		// if(fileChooser == null){
		// fileChooser = new JFileChooser();
		// }
		int returnVal = fileChooser.showOpenDialog(frame);

		if (returnVal == JFileChooser.APPROVE_OPTION) {
			File file = fileChooser.getSelectedFile();
			LogPane.println("Opening: " + file.getName());

			if (fileOpener == null) {
				fileOpener = new FileOpener();
			}
			fileOpener.setFile(file);
			fileOpener.start();

		} else {
			LogPane.println("Open command cancelled by user.");
		}

	}

	public void saveFile() {

		if (rdfTreePanel.getTopModelFilename() == null) {
			saveAsFile();
		}
		save();
	}

	public void save() {
		RdfUtils.store(rdfTreePanel.getTopModel(), rdfTreePanel
				.getTopModelFilename());
	}

	public void saveAsFile() {

		// FileChooserWrapper getFileChooser
		String filename = null;
		try {
			filename = FileChooserWrapper.getFileChooser().saveDialog()
					.toString();
		} catch (Exception exception) {
			System.out.println("Export aborted");
			return;
		}
		if (filename != null) {
			rdfTreePanel.setTopModelFilename(filename);
			save();
		}
	}



	public void valueChanged(TreeSelectionEvent event) {
		Object object = rdfTreePanel.getTree().getLastSelectedPathComponent();

		if ((object == null)) {
			return;
		}

		RdfTreeNode node = (RdfTreeNode) object;
		nodePanel.setRdfTreeNode(node);
	}

	public void displayModel() {
		// TODO make more consistent
		System.out.println(tabs.getSelectedComponent());
		
		rdfTreePanel.reload();
		rdfTreePanel.repaint();
		
		turtle.refreshFromModel();
		abbrev.refreshFromModel();
	}

	private Cursor normalCursor;
	private Cursor normalTreeCursor;

	public void waitCursor(boolean wait) {
		if (wait) {
			normalCursor = frame.getCursor();
			normalTreeCursor = rdfTreePanel.getCursor();
			frame.setCursor(new Cursor(Cursor.WAIT_CURSOR));
			rdfTreePanel.setCursor(new Cursor(Cursor.WAIT_CURSOR));
		} else {
			frame.setCursor(normalCursor);
			rdfTreePanel.setCursor(normalTreeCursor);
			frame.setCursor(normalCursor);
			rdfTreePanel.setCursor(normalTreeCursor);
		}
	}

	public void exit() {
		// save first?
		// System.exit(0);
		frame.dispose();
	}

	public void logPrintln(String string) {

	}

	public void logPrintErr(String string) {
		LogPane.err(string);
	}

	class FileOpener extends Thread {

		File file;

		public void setFile(File file) {
			this.file = file;
		}

		public void run() {
			waitCursor(true);

			// model = new ModelMem();
			try {
				// hacky for now
				String name = file.getName();
				String rdfLang = "RDF/XML";

				if (name.endsWith(".n3")) {
					rdfLang = "N3";
				}
				if (name.endsWith(".nt")) {
					rdfLang = "N-TRIPLE";
				}

				model.read(new FileReader(file), "", rdfLang);
			} catch (Exception exception) {
				// this.editor.logPane.err(exception.getMessage());
				logPrintErr(exception.getMessage());
				exception.printStackTrace();
			}
			logPrintln("Loaded");
			// rdfTreePanel.setModel(model); // TODO horrid!!
			rdfTreePanel.setTopModel(model);
			rdfTreePanel.setTopModelFilename(file.toString());

			displayModel();
			waitCursor(false);
			// RdfUtils.show(this.editor.treePanel.getTopModel());

		}

	}

	public void closeFile() {
		throw new RuntimeException("not yet implemented");
	}

	public void cloneFile() {
		throw new RuntimeException("not yet implemented");
	}

	/*
	 * public void stateChanged(ChangeEvent e) {
	 * System.out.println("STATECHANGED IN RDFEDITOR"); displayModel();
	 *  }
	 */
	public RdfTreePanel getTreePanel() {
		return rdfTreePanel;
	}

	// TODO refactor out
	public void setModel(Model model) {
		this.model = model;
		turtle.setModel(model);
		abbrev.setModel(model);
		System.out.println("setting model");
		displayModel();
	}

}
